

#ifndef __TC_H__
#define __TC_H__

extern unsigned int g_uiSucc;
extern unsigned int g_uiFail;

#define IPV4_START  0x10101000

static inline bool STRING_Equal(const char *src, const char *dst)
{
	if (0 == strcmp(src, dst)) return true;
    else return false;
}

static inline unsigned int GET_Rate(unsigned long long uiCount, unsigned long long uiUCost)
{
	unsigned long long uiRate;
	
	if (0 == uiUCost)
		uiRate = uiCount*1000;
	else
		uiRate = (uiCount*1000)/uiUCost;

	return (unsigned int)uiRate;
}

static inline void TEST_PrintOut(const char* pcFunction, const char* fmt, ...)
{
    char szLogText[512];

    va_list argptr;    
    va_start(argptr, fmt);    
    vsnprintf(szLogText, sizeof(szLogText), fmt, argptr);
    va_end(argptr);

    printf("    %s: %s\n", pcFunction, szLogText);
}

static inline void TEST_StartLog(const char *pcFunction)
{
    g_uiSucc = 0;
    g_uiFail = 0;
    printf("%s:\n", pcFunction);
    printf("{\n");
}
static inline void TEST_ResultUIntLog(const char *pcFunction, const char *pcTag, unsigned int uiWanted, unsigned int uiResult)
{
    if (uiWanted == uiResult)
    {
        g_uiSucc++;
        printf("    %s: %s succ {wanted=%u, result=%u}\n", pcFunction, pcTag, uiWanted,  uiResult);
    }
    else
    {
        g_uiFail++;
        printf("    %s: %s fail {wanted=%u, result=%u}\n", pcFunction, pcTag, uiWanted,  uiResult);
    }
}
static inline void TEST_ResultStringLog(const char *pcFunction, const char *pcTag, const char* pcWanted, const char* pcResult)
{
    if (0 == strcmp(pcWanted, pcResult))
    {
        g_uiSucc++;
        printf("    %s: %s succ {wanted=%s, result=%s}\n", pcFunction, pcTag, pcWanted, pcResult);
    }
    else
    {
        g_uiFail++;
        printf("    %s: %s fail {wanted=%s, result=%s}\n", pcFunction, pcTag, pcWanted, pcResult);
    }
}
static inline void TEST_EndLog(const char *pcFunction)
{
    if ((g_uiSucc + g_uiFail) > 0)
    {
        printf("    %s: %u/%u, execute succ rate %u%%\n", 
               pcFunction, g_uiSucc, g_uiFail, 
               (g_uiSucc*100)/(g_uiSucc+g_uiFail));
        LOGGER("%s: %u/%u, execute succ rate %u%%", 
               pcFunction, g_uiSucc, g_uiFail, 
               (g_uiSucc*100)/(g_uiSucc+g_uiFail));
    }
    printf("}\n");
    printf("\n");
    g_uiSucc = 0;
    g_uiFail = 0;
}

#define TEST_START()  TEST_StartLog(__FUNCTION__)
#define TEST_PRINT_OUT(fmt, ...)  TEST_PrintOut(__FUNCTION__, fmt, ##__VA_ARGS__)
#define TEST_CHECK_INT(TAG, WANTED, RESULT)  TEST_ResultUIntLog(__FUNCTION__, TAG, WANTED, RESULT)
#define TEST_CHECK_STRING(TAG, WANTED, RESULT)  TEST_ResultStringLog(__FUNCTION__, TAG, WANTED, RESULT)

/*
#define TEST_CHECK_OBJ_NORMAL_MATCH(TAG, TYPE, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stSlowMatchRet; \
    stSlowMatchRet = MATCH_FIRST_RULE_BY_OBJ(TYPE, OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stSlowMatchRet.szRuleName); \
}
*/
#define CHECK_SRC_IPV4_NORMAL_MATCH(TAG, IPV4, WANTED) \
{ \
    RULE_SUMMARY_S stSlowMatchRet; \
    stSlowMatchRet = MATCH_FIRST_RULE_BY_SRC_IPV4(IPV4); \
    TEST_CHECK_STRING(TAG, WANTED, stSlowMatchRet.szRuleName); \
}
#define CHECK_DEST_IPV4_NORMAL_MATCH(TAG, IPV4, WANTED) \
{ \
    RULE_SUMMARY_S stSlowMatchRet; \
    stSlowMatchRet = MATCH_FIRST_RULE_BY_DEST_IPV4(IPV4); \
    TEST_CHECK_STRING(TAG, WANTED, stSlowMatchRet.szRuleName); \
}
/*
#define TEST_CHECK_OBJ_QUICK_MATCH(TAG, TYPE, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stMatchRet; \
    stMatchRet = QUICK_MATCH_OBJ(TYPE, OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stMatchRet.szRuleName); \
}

#define TEST_CHECK_OBJ_QUICK_MATCH_BITMAP(TAG, TYPE, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stMatchRet; \
    stMatchRet = QUICK_MATCH_BITMAP_OBJ(TYPE, OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stMatchRet.szRuleName); \
}
*/

#define CHECK_SRC_IPV4_SWIFT_MATCH_BITMAP(TAG, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stMatchRet; \
    stMatchRet = SWIFT_MATCH_SRC_IPV4(OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stMatchRet.szRuleName); \
}

#define CHECK_DEST_IPV4_SWIFT_MATCH_BITMAP(TAG, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stMatchRet; \
    stMatchRet = SWIFT_MATCH_DEST_IPV4(OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stMatchRet.szRuleName); \
}

/*
#define TEST_CHECK_IPV4_FORMAL_QUICK_MATCH(TAG, OBJ, WANTED) \
{ \
    RULE_SUMMARY_S stMatchRet; \
    stMatchRet = QUICK_MATCH_IPV4(OBJ); \
    TEST_CHECK_STRING(TAG, WANTED, stMatchRet.szRuleName); \
}
*/

#define TEST_END()    TEST_EndLog(__FUNCTION__)


extern void SET_RUN_CPU(unsigned int uiCpu);

// CFG
extern void TEST_CFG_AddRule_Basic();
extern void TEST_CFG_AddRule_Speed();
extern void TEST_CFG_DelRule_Basic();
extern void TEST_CFG_DelRule_Speed();
extern void TEST_CFG_DelRule_Speed_Reverse();
extern void TEST_CFG_Append_Obj_Basic();
extern void TEST_CFG_DelRule_WithObj_Speed();
extern void TEST_CFG_Append_SrcIPv4_Basic();
extern void TEST_CFG_Append_SrcIPv4_Basic_Range2();
extern void TEST_CFG_SAVE_WithObject();

// MATCH_Normal_Obj
extern void TEST_MATCH_Normal_Obj_Basic();
extern void TEST_MATCH_Normal_Obj_Any();
extern void TEST_MATCH_Normal_Obj_BestSpeed();
extern void TEST_MATCH_Normal_Obj_10Speed();
extern void TEST_MATCH_Normal_Obj_20Speed();
extern void TEST_MATCH_Normal_Obj_50Speed();
extern void TEST_MATCH_Normal_Obj_100Speed();
extern void TEST_MATCH_Normal_Obj_1000Speed();
extern void TEST_MATCH_Normal_Obj_WorstSpeed();

// MATCH_Normal_IPv4
extern void TEST_MATCH_Normal_SrcIPv4_Basic();
extern void TEST_MATCH_Normal_SrcIPv4_Any();
extern void TEST_MATCH_Normal_SrcIPv4_BestSpeed();
extern void TEST_MATCH_Normal_SrcIPv4_10Speed();
extern void TEST_MATCH_Normal_SrcIPv4_20Speed();
extern void TEST_MATCH_Normal_SrcIPv4_50Speed();
extern void TEST_MATCH_Normal_SrcIPv4_100Speed();
extern void TEST_MATCH_Normal_SrcIPv4_1000Speed();
extern void TEST_MATCH_Normal_SrcIPv4_WorstSpeed();

extern void TEST_MATCH_Normal_DestIPv4_Basic();
extern void TEST_MATCH_Normal_DestIPv4_Any();
extern void TEST_MATCH_Normal_DestIPv4_BestSpeed();
extern void TEST_MATCH_Normal_DestIPv4_10Speed();
extern void TEST_MATCH_Normal_DestIPv4_20Speed();
extern void TEST_MATCH_Normal_DestIPv4_50Speed();
extern void TEST_MATCH_Normal_DestIPv4_100Speed();
extern void TEST_MATCH_Normal_DestIPv4_1000Speed();
extern void TEST_MATCH_Normal_DestIPv4_WorstSpeed();

// DBG RBT
extern void DBG_RBT_Operate();

// DBG CUT_IPV4
extern void DBG_CUT_IPV4_Point();
extern void DBG_CUT_IPV4_Range_All();
extern void DBG_CUT_IPV4_Range_Part();
extern void DBG_CUT_IPV4_Range_Any();
extern void DBG_CUT_IPV4_Range_All_Reverse();
extern void DBG_CUT_IPV4_Range_Part_Reverse();
extern void DBG_CUT_IPV4_Range_Part_Speed();
extern void DBG_CUT_IPV4_Range_Part_MemoryLeak();

// QUICK_Build_Commit
extern void TEST_QUICK_Build_Commit();

// QUICK_Match_Obj
extern void TEST_QUICK_Match_Obj_Any();
extern void TEST_QUICK_Match_Obj_NoModify();
extern void TEST_QUICK_Match_Obj_NotFound();
extern void TEST_QUICK_Match_Obj_Modify();
extern void TEST_QUICK_Match_Obj_ModifySpeed();

// TEST_QUICK_Match_IPv4
extern void TEST_QUICK_Match_IPv4_Point();
extern void TEST_QUICK_Match_IPv4_Any();
extern void TEST_QUICK_Match_IPv4_NoModify();
extern void TEST_QUICK_Match_IPv4_NotFound();
extern void TEST_QUICK_Match_IPv4_Modify();
extern void TEST_QUICK_Match_IPv4_ModifySpeed();

// DBG_BITMAP
extern void DBG_BITMAP_GET_FIRST();

// BITMAP_Match_Obj
extern void TEST_BITMAP_Match_Obj_Any();
extern void TEST_BITMAP_Match_Obj_NoModify();
extern void TEST_BITMAP_Match_Obj_NotFound();
extern void TEST_BITMAP_Match_Obj_Modify();
extern void TEST_BITMAP_Match_Obj_ModifySpeed();

// BITMAP_Match_SrcIPv4
extern void TEST_BITMAP_Match_SrcIPv4_Point();
extern void TEST_BITMAP_Match_SrcIPv4_Range();
extern void TEST_BITMAP_Match_SrcIPv4_Any();
extern void TEST_BITMAP_Match_SrcIPv4_NoModify();
extern void TEST_BITMAP_Match_SrcIPv4_NotFound();
extern void TEST_BITMAP_Match_SrcIPv4_Modify();
extern void TEST_BITMAP_Match_SrcIPv4_ModifySpeed();

// BITMAP_Match_DestIPv4
extern void TEST_BITMAP_Match_DestIPv4_Any();
extern void TEST_BITMAP_Match_DestIPv4_NoModify();
extern void TEST_BITMAP_Match_DestIPv4_NotFound();
extern void TEST_BITMAP_Match_DestIPv4_Modify();
extern void TEST_BITMAP_Match_DestIPv4_ModifySpeed();

// Random Test
extern void TEST_Random_Quick_Match_Obj();
extern void TEST_Random_Bitmap_Match_Obj();
extern void TEST_Random_Quick_Match_IPv4();
extern void TEST_Random_Bitmap_Match_SrcIPv4();
extern void TEST_Random_Quick_Match_Obj_Speed();
extern void TEST_Random_Bitmap_Match_Obj_Speed();
extern void TEST_Random_Quick_Match_IPv4_Speed();
extern void TEST_Random_Bitmap_Match_SrcIPv4_Speed();

extern void TEST_Random_Bitmap_Match_DestIPv4_Speed();

// Memory leak
extern void TEST_SWIFT_Valgrind_MemoryLeak();

// Formal
extern void TEST_FORMAL_QUICK_Match_Obj_Point();
extern void TEST_FORMAL_QUICK_Match_IPv4_Point();
extern void TEST_FORMAL_QUICK_Match_Obj_IPv4();

#endif

